We load the UofT dataset since it is the most complete dataset from last year
import pandas as pd
import numpy as np
import plotly
import plotly.plotly as py
import plotly.graph_objs as go
from helpers.processing import *
import glob
plotly.offline.init_notebook_mode(connected=True)
dfs = []
for f in glob.glob("../Data.nosync/CSVs/UofT/*.csv"): #loads every csv into the list as a pd dataframe
df = remove_stopped(pd.read_csv(f, header=12, low_memory=False)[1:], 10, 10, 0.002) #remove ticks where car is stopped
df = smooth_points(df.astype(float), 5) #average every 5 samples to reduce memory load (tickrate 0.002 -> 0.01)
dfs.append(df)
By graphing the acceleration against the brake pressure we can evaluate the brake performance thoughout the runs. We cut off samples with speed below 50 to reduce visual clutter.
dfs[0].head(3) #Sanity Check - If the first three rows are correct, it follows by undergraduate induction that everything is fine.
We can then plot the acceleration (negative in this case), against the brake pressure, with color representing the ground speed. Use the dropdown to select which run the data is from.
plt_data = []
for i in range(len(dfs)):
df = dfs[i].loc[(dfs[i]['Ground Speed'] > 50) &(dfs[i]['Brake Pres Front'] > 50)]
plt_data += [go.Scatter(
x=df['Brake Pres Front'],
y=df['Vehicle Accel Long'],
mode='markers',
marker=dict(color=df['Ground Speed'], colorscale='Viridis', showscale=True),
visible=(True if i == 0 else False))
]
menu = list([ dict(active=0,
buttons=[ dict(label = 'Run ' + str(i+1),
method = 'update',
args = [{'visible': [False if j != i else True for j in range(len(dfs))]}, {'title': 'Run '+str(i +1) + ' Braking'}]) for i in range(len(dfs))]
) ])
plt_layout = go.Layout(title='Brake Efficacy',
yaxis=dict(title='Acceleration (G)'),
xaxis=dict(title='Brake Pressure (psi) '),
updatemenus=menu)
fig = go.Figure(data=plt_data, layout=plt_layout)
plotly.offline.iplot(fig,filename='JupyterUno')
You might notice that little line on the right hand side of the graph for each run. Those are, of course, the points where we apply maximal brake pressure. Let's have a closer look. I've flipped the acceleration to deceleration and grouped the data points by speed.
plt_data = []
for i in range(len(dfs)):
df = dfs[i].loc[(dfs[i]['Brake Pres Front'] > 179)]
df = df.groupby(df['Ground Speed'] // 25).mean() #group the dataframe into splits of 25 km
df['decel'] = df['Vehicle Accel Long'] * -1
plt_data += [go.Bar(x= ['25','50','75','100','125','150','175','200'], y=df['decel'], name='Run ' + str(i+1))]
plt_layout = go.Layout(title='Brake Efficacy', yaxis=dict(title='Deceleration (G)'), xaxis=dict(title='Ground Speed (km/h)'))
fig = go.Figure(data=plt_data, layout=plt_layout)
plotly.offline.iplot(fig,filename='JupyterDos')
Again, this is only looking at total braking performance (i.e. when the pedal is fully pressed). We can render the same graph from the earlier data as well (i.e all points with braking pressure above 50 psi).
plt_data = []
for i in range(len(dfs)):
df = dfs[i].loc[(dfs[i]['Brake Pres Front'] > 50)]
df = df.groupby(df['Ground Speed'] // 25).mean() #group the dataframe into splits of 25 km
df['decel'] = df['Vehicle Accel Long'] * -1
plt_data += [go.Bar(x= ['25','50','75','100','125','150','175','200'], y=df['decel'], name='Run ' + str(i+1))]
plt_layout = go.Layout(title='Brake Efficacy', yaxis=dict(title='Deceleration (G)'), xaxis=dict(title='Ground Speed (km/h)'))
fig = go.Figure(data=plt_data, layout=plt_layout)
plotly.offline.iplot(fig,filename='JupyterTres')
Interestingly, run 4 has noticably reduced perfomance compared to run 3 at higher speeds. Run 6 was only slightly better than the two following runs. We can of course make the same plots for acceleration too. The bar chart below plots the average acceleration at each speed interval (i.e 0-25, 25-50 etc) when the throttle is at > 50%.
plt_data = []
for i in range(len(dfs)):
df = dfs[i].loc[(dfs[i]['Throttle'] > 50)]
df = df.groupby(df['Ground Speed'] // 25).mean() #group the dataframe into splits of 25 km
plt_data += [go.Bar(x= ['25','50','75','100','125','150','175','200'], y=df['Vehicle Accel Long'], name='Run ' + str(i+1))]
plt_layout = go.Layout(title='Acceleration at Different Speeds', yaxis=dict(title='Accel (G)'), xaxis=dict(title='Ground Speed (km/h)'))
fig = go.Figure(data=plt_data, layout=plt_layout)
plotly.offline.iplot(fig,filename='JupyterQuatro')
Judging from the above two graphs, the best performance out of all runs was #6. Of course, if you prefer a scatterplot, we can do that too! Here color represents the speed.
plt_data = []
for i in range(len(dfs)):
df = dfs[i].loc[(dfs[i]['Ground Speed'] > 25) &(dfs[i]['Throttle'] > 50)]
plt_data += [go.Scatter(x=df['Throttle'], y=df['Vehicle Accel Long'],mode='markers',marker=dict(color=df['Ground Speed'], colorscale='Jet', showscale=True), visible=(True if i == 0 else False))]
menu = list([ dict(active=0, buttons=[ dict(label = 'Run ' + str(i+1), method = 'update', args = [{'visible': [False if j != i else True for j in range(len(dfs))]}, {'title': 'Run '+str(i +1) + ' Acceleration'}]) for i in range(len(dfs))]
) ])
plt_layout = go.Layout(title='Acceleration at Different Throttle Positions', yaxis=dict(title='Acceleration (G)'), xaxis=dict(title='Throttle (%)'), updatemenus=menu)
fig = go.Figure(data=plt_data, layout=plt_layout)
plotly.offline.iplot(fig,filename='JupyterCinco')
We can then determine the nearest corner to each data point, and use that to construct statistics about our speed at different parts of the track (where -1 represents a straight).
#we'll need this in a minute
def closest(x, ng):
global last#badbadbadnotgood
if last < 0:
dist_lst = [distance(x, k) for k in corners]
if min(dist_lst) < ng:
last = int(np.argmin([distance(x, k) for k in corners]))
return last
else:
return -1
else:
dist_lst = [distance(x, corners[last]), distance(x, corners[(last+1) % len(corners)])]
if min(dist_lst) < ng:
last = (np.argmin(dist_lst) + last)%len(corners)
return last
else:
return -1
#if you call this on a constant dataframe a black hole is formed
def normal(frame):
return (frame - frame.min()) / (frame.max() - frame.min())
corners = [(0.147,0.937),(0.11, 0.552), (0.264,0.531), (0.341,0.814), (0.406, 0.659), (0.589, 0.032), (0.756, 0.058),(0.588, 0.355), (0.770, 0.357), (0.902, 0.440)]
df = pd.concat([d[300:-2000] for d in dfs[1:3]], ignore_index=True)
df = smooth_points(df, 5)#too many points otherwise
#Normalize the x, y coordinates
df['x'] = normal(df['GPS Longitude'])
df['y'] = normal(df['GPS Latitude'])
last = 0
df['close'] = df[['x','y']].apply(lambda x: closest( (x[0], x[1]), 0.1), axis=1)
plt_data = [go.Scatter(x=df['x'], y=df['y'], mode='markers', marker=dict(color=df['close'], colorscale='Jet', showscale=True))]
plt_layout = go.Layout(title='Nearest Corner', yaxis=dict(title='y'), xaxis=dict(title='x'))
fig = go.Figure(data=plt_data, layout=plt_layout)
plotly.offline.iplot(fig,filename='JupyterSeis')
Crude, but workable. We can then average corner speed as follows.
plt_data = []
for i in range(len(dfs)):
df = dfs[i]
df['x'] = normal(df['GPS Longitude'])
df['y'] = normal(df['GPS Latitude'])
last = 0
df['close'] = df[['x','y']].apply(lambda x: closest( (x[0], x[1]), 0.1), axis=1).map(str)
plt_data += [go.Bar(x= [str(j) for j in range(len(corners) + 1)],y=df.groupby('close')['Ground Speed'].mean(), name = 'Run' +str(i))]
plt_layout = go.Layout(title='Corner Speed', yaxis=dict(title='Speed km/h'), xaxis=dict(title='Corner'))
fig = go.Figure(data=plt_data, layout=plt_layout)
plotly.offline.iplot(fig,filename='JupyterSiete')
plt_data = []
for i in range(len(dfs)):
df = dfs[i]
X = normal(df['GPS Longitude'])
Y = normal(df['GPS Latitude'])
Z = df[['Susp Pos FL', 'Susp Pos RR']].mean(axis=1)
plt_data += [go.Scatter3d(x=X, y=Y, z=Z, mode='markers', marker=dict(size=5, color=df['Time'], colorscale='Viridis', showscale=True),visible=(True if i == 0 else False))]
menu = list([ dict(active=0, buttons=[ dict(label = 'Run ' + str(i+1), method = 'update', args = [{'visible': [False if j != i else True for j in range(len(dfs))]}, {'title': 'Run '+str(i +1) + ' Suspension Position'}]) for i in range(len(dfs))]
) ])
plt_layout = go.Layout(title='Suspension', yaxis=dict(title='GPS Latitude'), xaxis=dict(title='GPS Longitude'), updatemenus=menu)
fig = go.Figure(data=plt_data, layout=plt_layout)
plotly.offline.iplot(fig,filename='JupyterOcho')